#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <asm/io.h>

char *name = "xdrv";

// 正确定义驱动属性的show函数
static ssize_t drvname_show(struct device_driver *drv, char *buf)
{
    return sprintf(buf, "%s\n", name);
}

// 定义驱动属性结构，这会生成driver_attr_drvname变量
//static DRIVER_ATTR_RO(drvname);
static DRIVER_ATTR(drvname, 0444, drvname_show, NULL);

extern struct bus_type xbus;

int xdrv_probe(struct device *dev)
{
    printk("%s-%s\n", __FILE__, __func__);
    return 0;
}

int xdrv_remove(struct device *dev)
{
    printk("%s-%s\n", __FILE__, __func__);
    return 0;
}

static struct device_driver xdrv = {
    .name = "xdev",
    .bus = &xbus,
    .probe = xdrv_probe,
    .remove = xdrv_remove,
};

static __init int xdrv_init(void)
{
    int ret;
    printk("xdrv init\n");
    
    ret = driver_register(&xdrv);
    if (ret) {
        printk("driver register failed\n");
        return ret;
    }
    
    // 现在可以正确引用宏生成的变量了
    ret = driver_create_file(&xdrv, &driver_attr_drvname);
    if (ret) {
        printk("create driver file failed\n");
        driver_unregister(&xdrv);
        return ret;
    }
    
    return 0;
}
module_init(xdrv_init);

static __exit void xdrv_exit(void)
{
    printk("xdrv exit\n");
    driver_remove_file(&xdrv, &driver_attr_drvname);
    driver_unregister(&xdrv);
}
module_exit(xdrv_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("embedfire ");
MODULE_DESCRIPTION("hello module");
MODULE_ALIAS("test_module");
